#ifndef __SECTOR_MON_H__
#define __SECTOR_MON_H__


#include <ntifs.h>
#include <Ntddvol.h>

#define DEVICE_TYPE_CTRL			0
#define DEVICE_TYPE_FILTER			1

typedef struct _DISK_FLT_DEVICE_EXT {

	ULONG DeviceType;
	PDEVICE_OBJECT FilterDeviceObject;
	PDEVICE_OBJECT LowerDeviceObject;
	PDEVICE_OBJECT PhysicalDeviceObject;

	LIST_ENTRY ReqList;
	KSPIN_LOCK ReqLock;
	KEVENT ReqEvent;
	BOOLEAN ThreadFlag;
	PETHREAD ThreadObject;
	PAGED_LOOKASIDE_LIST WriteElemHeader;
	PAGED_LOOKASIDE_LIST SectorBufHeader;

} DISK_FLT_DEVICE_EXT, *PDISK_FLT_DEVICE_EXT;


typedef struct _WRITE_ELEMENT {

	LIST_ENTRY ListEntry;
	HANDLE File;
	PVOID Buffer;
	ULONG Length;
	LARGE_INTEGER Offset;
	BOOLEAN NeedFree;
	ULONG Tag;

} WRITE_ELEMENT, *PWRITE_ELEMENT;


typedef struct _GLOBAL_CONTEXT {

	HANDLE FileHandle;
	PVOID MapBuffer;
	ULONG MapSize;
	HANDLE SparseFileHandle;
} GLOBAL_CONTEXT, *PGLOBAL_CONTEXT;


#pragma pack(push, 1)

typedef struct _NTFS_BPB {
	USHORT	BytesPerSector;
	UCHAR	SectorsPerCluster;
	USHORT	ReservedSectors;
	UCHAR	NumberOfFATs;		// always 0
	USHORT	RootEntries;		// always 0
	USHORT	SmallSectors;		// not used by NTFS
	UCHAR	MediaDescriptor;
	USHORT 	SectorsPerFAT;		// always 0
	USHORT	SectorsPerTrack;
	USHORT	NumberOfHeads;
	ULONG	HiddenSectors;
	ULONG	LargeSectors;		//	not used by NTFS
} NTFS_BPB, *PNTFS_BPB;

typedef struct _NTFS_EXBPB {	// Extended BIOS parameter block for FAT16
	ULONG 		Reserved;		// not used by NTFS
	ULONGLONG	TotalSectors;
	ULONGLONG	MFT;
	ULONGLONG	MFTMirr;
	ULONG		ClustersPerFileRecordSegment;
	ULONG		ClustersPerIndexBlock;
	ULONGLONG	VolumeSerialNumber;
	ULONG		Checksum;
} NTFS_EXBPB, *PNTFS_EXBPB;

typedef struct _NTFS_BOOT_SEC {
	UCHAR		JumpInstruction[3];
	UCHAR		OemID[8];
	NTFS_BPB	Bpb;
	NTFS_EXBPB	ExBpb;
	UCHAR		BootstrapCode[426];
	UCHAR		EndOfSector[2];

} NTFS_BOOT_SEC, *PNTFS_BOOT_SEC;

#pragma pack(pop)

#define DIRECT_READ		0
#define DIRECT_WRITE	1


#define BITOFF_TO_MAPOFF(off)				(ULONG)(off >> 3)
#define BITLEN_TO_MAPLEN(off, len)			((ULONG)((off + len) >> 3) - BITOFF_TO_MAPOFF(off) + 1)

#define BYTEOFF_TO_BITOFF(off)				(off / BytesPerSector)
#define BYTELEN_TO_BITLEN(len)				(len / BytesPerSector)



NTSTATUS SkipAndCallDriver( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp );
NTSTATUS SyncIrpCompletionRoutine( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PVOID Context );
NTSTATUS SendSyncIrp( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp );
NTSTATUS DispatchPassThrough( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp );
NTSTATUS DispatchPower( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp );
NTSTATUS DispatchPnp( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp );
NTSTATUS DispatchReadWrite( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp );
NTSTATUS DispatchDeviceControl( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp );
NTSTATUS DirectReadWrite( __in PDEVICE_OBJECT DeviceObject, __in ULONG ReadWrite, __out PVOID Buffer, __in PLARGE_INTEGER Offset, __in ULONG Length );
LONGLONG GetFileSize( __in HANDLE Handle );
BOOLEAN __fastcall SetBit( __in PUCHAR BitBuf, __in ULONG BitSize, __in ULONGLONG Bit );
BOOLEAN __fastcall ClearBit( __in PUCHAR BitBuf, __in ULONG BitSize, __in ULONGLONG Bit );
ULONG __fastcall GetBit( __in PUCHAR BitBuf, __in ULONG BitSize, __in ULONGLONG Bit );
NTSTATUS OpenMapping( __in PWCHAR Name, __out PHANDLE File, __out PVOID *Buffer, __out ULONG *BufferSize );
VOID CloseMapping( __in HANDLE File, __in PVOID Buffer );
NTSTATUS CreateSparseFile( __out PHANDLE Handle, __in PWCHAR FileName, __in ULONGLONG FileSize, __in BOOLEAN Restore );
NTSTATUS AddDevice( __in PDRIVER_OBJECT DriverObject, __in PDEVICE_OBJECT PhysicalDeviceObject );
VOID Unload( __in PDRIVER_OBJECT DriverObject );
VOID ReinitializationRoutine( __in PDRIVER_OBJECT DriverObject, __in PVOID Context, __in ULONG Count );
NTSTATUS DriverEntry( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath );
NTSTATUS FlushBuffer( __in PDISK_FLT_DEVICE_EXT DevExt, __in HANDLE File, __in PVOID Buffer, __in ULONG Offset, __in ULONG Size );
NTSTATUS __fastcall BackupSectorAndSetBit( __in PDEVICE_OBJECT PhysicalDeviceObject, __in HANDLE File, __in PLARGE_INTEGER Offset, __in ULONG Length, __in PDISK_FLT_DEVICE_EXT DevExt );
VOID WriteWorkThread( __in PVOID Context );
NTSTATUS RestoreDisk( __in PDISK_FLT_DEVICE_EXT DevExt );
BOOLEAN IsRestoreDisk();
#endif